//
// Created by chen on 2023/6/23.
//
#include "machineRoom.h"

bool fileExistAndNotEmpty(string fileName){
    ifstream ifs;
    ifs.open(fileName, ios::in);
    if(!ifs.is_open()){
        ifs.close();
        return false;  //文件不存在
    }
    char ch;
    ifs>>ch;
    if(ifs.eof()){
        ifs.close();
        return false;  // 文件为空
    }
    ifs.close();
    return true;
}

MachineRoom::MachineRoom() {
    this->initTimeInfo();

    bool isReadRoomFile = fileExistAndNotEmpty(ROOMFILE);
    if(isReadRoomFile){
        this->initRoomInfo();
    } else{  // 文件为空
        cout << "roomFile.csv is not exist, please check" << endl;
        exit(-1);
    }

    bool isReadReservationFile = fileExistAndNotEmpty(RESERVATIONFILE);
    if(isReadReservationFile){
        this->initRoomReservation();
    } else{  // 文件为空
        for (map<string, string>::iterator vIt = this->timeInfo.begin(); vIt != this->timeInfo.end(); ++vIt) {
            for (map<string, string>::iterator mIt= this->roomInfo.begin(); mIt != this->roomInfo.end(); ++mIt) {
                this->idleRoom.insert(pair<string, string>(mIt->first, vIt->first));
            }
        }
    }
}

MachineRoom::~MachineRoom() {

}

void MachineRoom::initTimeInfo() {
    this->timeInfo.insert(pair<string, string>("1", "周一上午"));
    this->timeInfo.insert(pair<string, string>("2", "周一下午"));
    this->timeInfo.insert(pair<string, string>("3", "周二上午"));
    this->timeInfo.insert(pair<string, string>("4", "周二下午"));
    this->timeInfo.insert(pair<string, string>("5", "周三上午"));
    this->timeInfo.insert(pair<string, string>("6", "周三下午"));
    this->timeInfo.insert(pair<string, string>("7", "周四上午"));
    this->timeInfo.insert(pair<string, string>("8", "周四下午"));
    this->timeInfo.insert(pair<string, string>("9", "周五上午"));
    this->timeInfo.insert(pair<string, string>("10", "周五下午"));
}

// 初始化机房信息，读取文件
void MachineRoom::initRoomInfo() {
    ifstream ifs;
    ifs.open(ROOMFILE, ios::in);
    if(!ifs.is_open()){
        cout << "文件打开失败！" << endl;
        exit(-1);
    }
    string buf;
    while (getline(ifs, buf)){
        vector<string> temp;
        int start = 0;
        int pos = -1;
        while (true){
            pos = buf.find(",", start);
            if(pos == -1){
                break;
            }
            temp.push_back(buf.substr(start, pos-start));
            start = pos + 1;  // 因为此时pos指向,位置 故应该从pos+1开始找
        }
        for (vector<string>::iterator it= temp.begin(); it!= temp.end();) {
            this->roomInfo.insert(pair<string, string>(*it, *(it+1)));
            it += 2;
        }
    }
    ifs.close();
}

// 初始化预约信息，读取文件
void MachineRoom::initRoomReservation() {
    ifstream ifs;
    ifs.open(RESERVATIONFILE, ios::in);
    if(!ifs.is_open()){
        cout << "文件打开失败！" << endl;
        return;
    }
    getline(ifs, this->timeStamp);  // 先读取第一行的时间戳
    string buf;
    int lineNum = 1;   // 用于统计行数，每一行实例化到不同的map中
    while (getline(ifs, buf)){
        vector<string> temp;
        int start = 0;
        int pos = -1;
        while (true){
            pos = buf.find(",", start);
            if(pos == -1){
                break;
            }
            temp.push_back(buf.substr(start, pos-start));
            start = pos + 1;  // 因为此时pos指向,位置 故应该从pos+1开始找
        }
        for (vector<string>::iterator it= temp.begin(); it!= temp.end();) {
            if (lineNum == 1){
                this->idleRoom.insert(pair<string, string>(*it, *(it+1)));
                it += 2;
            } else if (lineNum == 2){
                map<string, string> userTemp;
                userTemp.insert((pair<string, string>(*(it+2), *(it+3))));
                map<string, map<string, string>> temp;
                temp.insert(pair<string, map<string, string>>(*(it+1), userTemp));
                this->reservationRoom.insert(pair<string, map<string, map<string, string>>>(*it, temp));
                it += 4;
            } else{
                map<string, string> temp;
                temp.insert(pair<string, string>(*(it+1), *(it+2)));
                this->occupyRoom.insert(pair<string, map<string, string>>(*it, temp));
                it += 3;
            }
        }
        lineNum++;
    }
    ifs.close();
}

// 获取当前时间戳
string getTimeStamp(){
    time_t timeStamp = time(NULL);
    return to_string(timeStamp);
}

// 获取文件中的时间戳
string getFileTimeStamp(){
    ifstream ifs;
    ifs.open(RESERVATIONFILE, ios::in);
    if(!ifs.is_open()){
        cout << "文件打开失败！" << endl;
        return "";
    }
    string buf;
    getline(ifs, buf);  //获取文件第一行储存的时间戳
    ifs.close();
    return buf;
}

string MachineRoom::getInfoByRoomId(string id) {
    if(id == "0"){
        return "最大容纳100人";
    }else if(id == "1"){
        return "最大容纳50人";
    } else if(id == "2"){
        return "最大容纳20人";
    }else {
        return "undefined id, please check";
    }
}

// 将当前时间戳，空闲机房，预约机房，被占用机房的信息写入到文件中
void MachineRoom::saveToFile() {
    ofstream ofs;
    ofs.open(RESERVATIONFILE, ios::out);
    if(!ofs.is_open()){
        cout << "文件打开失败！" << endl;
        return;
    }
    if(fileExistAndNotEmpty(RESERVATIONFILE)){   // 有文件且文件不为空，需要校验时间戳，否则不校验时间戳
        string fileTimeStamp = getFileTimeStamp();
        if(this->timeStamp != fileTimeStamp){
            cout << "当前机房信息已更新，写入失败，请重新获取机房预约信息后再试" << endl;
            return;
        }
    }
    this->timeStamp = getTimeStamp();
    ofs << this->timeStamp;
    ofs << endl;
    for (multimap<string, string>::iterator it= this->idleRoom.begin(); it!= this->idleRoom.end(); ++it) {
        ofs << it->first << "," << it->second << ",";
    }
    ofs << endl;
    for (multimap<string, map<string, map<string, string>>>::iterator it= this->reservationRoom.begin(); it!= this->reservationRoom.end(); ++it) {
        for (map<string, map<string, string>>::iterator it2 = it->second.begin(); it2 != it->second.end(); ++it2) {
            for (map<string, string>::iterator it3= it2->second.begin(); it3 != it2->second.end(); ++it3) {
                ofs << it->first << "," << it2->first << "," << it3->first << "," << it3->second << ",";
            }
        }
    }
    ofs << endl;
    for (multimap<string, map<string, string>>::iterator it= this->occupyRoom.begin(); it!= this->occupyRoom.end(); ++it) {
        for (map<string, string>::iterator it2= it->second.begin(); it2 != it->second.end(); ++it2) {
            ofs << it->first << "," << it2->first << "," << it2->second << ",";
        }
    }
    ofs << endl;
    ofs.close();
    cout << "当前机房占用信息已更新到文件中，时间戳=" << this->timeStamp << endl;
}

void MachineRoom::applyReservation(string roomId, string timeIndex, string userName) {
    map<string, string>::iterator tempIt = this->roomInfo.find(roomId);
    if (tempIt == this->roomInfo.end()){
        cout << "无此机房Id，插入失败" << endl;
        return;
    }
    map<string, string>::iterator tempIt2 = this->timeInfo.find(timeIndex);
    if (tempIt2 == this->timeInfo.end()){
        cout << "无此时间，插入失败" << endl;
        return;
    }
    for (multimap<string, map<string, string>>::iterator it= this->occupyRoom.begin(); it!= this->occupyRoom.end(); ++it) {
        if(it->first == roomId){
            for (map<string, string>::iterator it2= it->second.begin(); it2 != it->second.end(); ++it2) {
                if(it2->first == timeIndex){
                    cout << "预约失败，该机房此时间段已被占用，请重新选择" << endl;
                    return;
                }
            }
        }
    }
    for (multimap<string, string>::iterator it= this->idleRoom.begin(); it!= this->idleRoom.end(); ++it) {
        if(it->first == roomId && it->second == timeIndex){
            this->idleRoom.erase(it);   // 将该房间此时段从空闲房间map中删除
            map<string, string> userTemp;
            timeStamp = getTimeStamp();
            userTemp.insert((pair<string, string>(userName, timeStamp)));
            map<string, map<string, string>> temp;
            temp.insert(pair<string, map<string, string>>(timeIndex, userTemp));
            this->reservationRoom.insert(pair<string, map<string, map<string, string>>>(roomId, temp));  // 将其加入到预约map中
            cout << "预约成功" << endl;
            this->saveToFile();
            return;
        }
    }
    for (multimap<string, map<string, map<string, string>>>::iterator it= this->reservationRoom.begin(); it!= this->reservationRoom.end(); ++it) {
        if (it->first == roomId){
            for (map<string, map<string, string>>::iterator it2 = it->second.begin(); it2 != it->second.end(); ++it2) {
                if (it2->first == timeIndex){   // 当前机房此时间段已经在预约列表中，更新此列表，增加一条预约信息
                    for (map<string, string>::iterator it3= it2->second.begin(); it3 != it2->second.end(); ++it3) {
                        if(it3->first == userName){  // 同一用户一个机房同一时间段，不做处理，使用最早的记录
                            cout << "预约失败，该机房此时间段已被你预约，请重新选择" << endl;
                            return;
                        }
                    }
                }
            }
        }
    }
    map<string, string> userTemp;
    timeStamp = getTimeStamp();
    userTemp.insert((pair<string, string>(userName, timeStamp)));
    map<string, map<string, string>> temp;
    temp.insert(pair<string, map<string, string>>(timeIndex, userTemp));
    this->reservationRoom.insert(pair<string, map<string, map<string, string>>>(roomId, temp));  // 将其加入到预约map中
    cout << "预约成功" << endl;
    this->saveToFile();
}

void MachineRoom::viewSelfReservation(string userName) {
    bool hasReservation = false;
    for (multimap<string, map<string, map<string, string>>>::iterator it= this->reservationRoom.begin(); it!= this->reservationRoom.end(); ++it) {
        for (map<string, map<string, string>>::iterator it2 = it->second.begin(); it2 != it->second.end(); ++it2) {
            for (map<string, string>::iterator it3= it2->second.begin(); it3 != it2->second.end(); ++it3) {
                if(it3->first == userName){
                    cout << "机房" << it->first << this->timeInfo[it2->first] << "被你预约，正在审核中" << endl;
                    hasReservation = true;
                }
            }
        }
    }
    for (multimap<string, map<string, string>>::iterator it= this->occupyRoom.begin(); it!= this->occupyRoom.end(); ++it) {
        for (map<string, string>::iterator it2= it->second.begin(); it2 != it->second.end(); ++it2) {
            if(it2->second == userName){
                cout << "机房" << it->first << this->timeInfo[it2->first] << "被你预约成功，审核通过" << endl;
                hasReservation = true;
            }
        }
    }
    if(!hasReservation){
        cout << "没有你的预约信息!" << endl;
    }
}

void MachineRoom::viewAllReservation() {
    bool hasReservation = false;
    for (multimap<string, map<string, map<string, string>>>::iterator it= this->reservationRoom.begin(); it!= this->reservationRoom.end(); ++it) {
        for (map<string, map<string, string>>::iterator it2 = it->second.begin(); it2 != it->second.end(); ++it2) {
            for (map<string, string>::iterator it3= it2->second.begin(); it3 != it2->second.end(); ++it3) {
                cout << "机房" << it->first << this->timeInfo[it2->first] << "被" << it3->first << "预约，正在审核中" << endl;
                hasReservation = true;
            }
        }
    }
    for (multimap<string, map<string, string>>::iterator it= this->occupyRoom.begin(); it!= this->occupyRoom.end(); ++it) {
        for (map<string, string>::iterator it2= it->second.begin(); it2 != it->second.end(); ++it2) {
            cout << "机房" << it->first << this->timeInfo[it2->first] << "被" << it2->second << "预约成功，审核通过" << endl;
            hasReservation = true;
        }
    }
    if(!hasReservation){
        cout << "没有任何预约信息!" << endl;
    }
}

void MachineRoom::cancelReservation(string roomId, string timeIndex, string userName) {
    bool delSuccess = false;
    for (multimap<string, map<string, string>>::iterator it= this->occupyRoom.begin(); it!= this->occupyRoom.end(); ++it) {
        if(it->first == roomId){
            for (map<string, string>::iterator it2= it->second.begin(); it2 != it->second.end(); ++it2) {
                if(it2->first == timeIndex && it2->second == userName){
                    this->occupyRoom.erase(it);
                    cout << "已从预约成功(审核通过)列表中删除预约信息" << endl;
                    delSuccess = true;
                }
            }
        }
    }
    for (multimap<string, map<string, map<string, string>>>::iterator it= this->reservationRoom.begin(); it!= this->reservationRoom.end(); ++it) {
        if (it->first == roomId){
            for (map<string, map<string, string>>::iterator it2 = it->second.begin(); it2 != it->second.end(); ++it2) {
                if (it2->first == timeIndex){   // 当前机房此时间段已经在预约列表中，更新此列表，增加一条预约信息
                    for (map<string, string>::iterator it3= it2->second.begin(); it3 != it2->second.end(); ++it3) {
                        if(it3->first == userName){  // 同一用户一个机房同一时间段，不做处理，使用最早的记录
                            this->reservationRoom.erase(it);
                            cout << "已从预约(等待审核)列表中删除预约信息" << endl;
                            delSuccess = true;
                        }
                    }
                }
            }
        }
    }
    if(!delSuccess){
        cout << "无此预约信息，取消预约失败" << endl;
        return;
    } else{
        this->saveToFile();  // 将取消预约信息保存到文件中
    }
}

void MachineRoom::checkReservation(string roomId, string timeIndex, string userName, string yesOrNo) {
    bool checkSuccess = false;
    for (multimap<string, map<string, map<string, string>>>::iterator it= this->reservationRoom.begin(); it!= this->reservationRoom.end(); ++it) {
        if (it->first == roomId){
            for (map<string, map<string, string>>::iterator it2 = it->second.begin(); it2 != it->second.end(); ++it2) {
                if (it2->first == timeIndex){
                    for (map<string, string>::iterator it3= it2->second.begin(); it3 != it2->second.end(); ++it3) {
                        if(it3->first == userName){
                            if (yesOrNo == "1"){
                                this->reservationRoom.erase(it);
                                cout << "审核通过！" << endl;
                                map<string, string> temp;
                                temp.insert(pair<string, string>(timeIndex, userName));
                                this->occupyRoom.insert(pair<string, map<string, string>>(roomId, temp)); // 将占用信息更新到occupyRoom中
                                checkSuccess = true;
                            }else {
                                this->reservationRoom.erase(it);
                                cout << "审核不通过！" << endl;
                                checkSuccess = true;
                            }
                        }
                    }
                }
            }
        }
    }
    if(!checkSuccess){
        cout << "审核失败，无此条需要审核消息" << endl;
    }else {
        this->saveToFile();
    }
}

void MachineRoom::viewRoomInfo() {
    for (map<string, string>::iterator it= this->roomInfo.begin(); it!= this->roomInfo.end(); ++it) {
        cout << "机房编号:" << it->first << ", 机房容量:" << this->getInfoByRoomId(it->second) << endl;
    }
}

void MachineRoom::clearAllReservation() {
    ofstream ofs;
    ofs.open(RESERVATIONFILE, ios::trunc);
    ofs.close();
    cout << "清空成功！" << endl;
}

